<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>24 Ways</title>
</head>
<body>
	<div id='app'>aaa</div>
</body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">

// 	在函数内部，有两个特殊的对象：arguments 和 this。其中，arguments 在第 3 章曾经介绍过，
// 它是一个类数组对象，包含着传入函数中的所有参数。虽然 arguments 的主要用途是保存函数参数，
// 但这个对象还有一个名叫 callee 的属性，该属性是一个指针，指向拥有这个 arguments 对象的函数。
// 请看下面这个非常经典的阶乘函数。

// 当函数被调用的时候创建一个caller,caller指向调用这个函数的函数，如果是在全局作用域中调用当前函数，它的值为 null。

// Object.prototype.toString.call(a)//精确判断数据类型
// instanceof 只能用来判断构造函数

// num.toFixed(2) //保留2位小数
	
	// 经典的递归
	/*function factor(num) {
		// console.log('arguments',arguments)
		if(num<=1){
			return num;
		}else{
			return num*arguments.callee(num-1)
		}
	}
	console.log(factor(4))*/



	/*
	function outer(){
	     inner();
	}
	function inner(){
	     alert(inner.caller);
	}
	outer();

	function outer(){
	 inner();
	}
	function inner(){
		console.log(arguments)
	 alert(arguments.callee.caller);
	}
	outer(); 
	*/



	/*
	function sum(sum1,sum2){
		return sum1+sum2
	}

	function callSum1(num1,num2){
		return sum.apply(this,arguments)
	}

	console.log('sum',sum)
	console.log('sum',sum.prototype)
	*/



	// 精确判断数据类型
	/*
	const a= {name:'1'};
	console.log('a',a)
	console.log('a',Object.prototype.toString.call(a))
	console.log('a',typeof(a))
	console.log('a',a.__proto__)

	var num=132.123;
	alert(num.toFixed(2))
	*/



	/*
	var book = {
	 _year: 2004,
	 edition: 1
	};
	Object.defineProperty(book, "year", {
	 get: function(){
	 return this._year;
	 },
	 set: function(newValue){
	 if (newValue > 2004) {
	 this._year = newValue;
	 this.edition += newValue - 2004;
	 }
	 }
	});
	book.year = 2005;
	console.log('book',book.edition); //2 
	console.log('book',Object.getOwnPropertyDescriptor(book,'_year'))
	*/



	// function Person(name, age, job){
	//  this.name = name;
	//  this.age = age;
	//  this.job = job;
	//  this.sayName = function(){
	//  alert(this.name);
	//  };
	// }
	// var person1 = new Person("Nicholas", 29, "Software Engineer"); 
	// console.log('Person',Person.prototype.constructor)
	// console.log('person1',person1.__proto__.constructor)

	// class People{
	// 	constructor(name,sex){
	// 		this.name = name;
	// 		this.sex = sex;
	// 	}
	// 	getName(){
	// 		return this.name
	// 	}
	// }

	// const people = new People('xw',1)

	// console.log('people',people.getName())


	/*
	function Person(){

	}

	Person.prototype={//字面量方式创建constructor就不在属于他
		name:'xw',
		sex:'1',
		getName:function(){
			alert(this.name)
		}
	}

	//重设构造函数，只适用于 ECMAScript 5 兼容的浏览器
	Object.defineProperty(Person.prototype, "constructor", {
	 enumerable: false,//这是为false，在for in中就无法取到constructor属性
	 value: Person
	}); 

	const person1 = new Person();
	const person2 = new Person();

	person1.name='zy'

	var keys = Object.keys(Person.prototype);
	alert(keys)//name,sex,getName

	var keys1 = Object.keys(person1);
	alert(keys1)//name

	console.log('hasOwnProperty',person1.hasOwnProperty('name'))
	console.log('name' in person1)
	

	console.log('person',Person.prototype)
	console.log('person1',person1.__proto__)
	console.log('person2',person2.__proto__)
	console.log(Object.getPrototypeOf(person1))//获取对象的原型
	console.log('person1',person1.name)
	console.log('person2',person2.name)
	console.log('getName',person1.getName())
	delete person1.name;
	console.log('person1',person1.name)

	console.log('hasOwnProperty',person1.hasOwnProperty('name'))
	console.log('name' in person1)
	*/


	/*
	//尽管可以这样做，但我们不推荐在产品化的程序中修改原生对象的原型。如果因
	//某个实现中缺少某个方法，就在原生对象的原型中添加这个方法，那么当在另一个支
	//持该方法的实现中运行代码时，就可能会导致命名冲突。而且，这样做也可能会意外
	//地重写原生方法。
	String.prototype.startWidth=function(text){

		return this.indexOf(text) <0;

	}
	const man = 'hello';
	console.log(man.startWidth('a'))
	*/



	/*
	function SuperType(){
		this.property = true;
	}

	SuperType.prototype.getSuperValue=function(){
		return this.property
	}

	function SubType(){
		this.subproperty = false; 
	}
	// SubType继承了SuperType
	SubType.prototype = new SuperType(); 

	SubType.prototype.getSubValue= function(){
		return this.subproperty
	}

	var instance = new SubType();

	console.log('property',instance.property)
	console.log('subproperty',instance.subproperty)

	console.log(Object.prototype)
	*/



	// 借用构造函数
	/*
	function SuperType(name){
	 	this.name = name;
	}
	function SubType(name){
	 	//继承了 SuperType
	 	SuperType.call(this,name);
	}
	var instance1 = new SubType('xw');
	// instance1.colors.push("black");
	// alert(instance1.name); //"red,blue,green,black"
	var instance2 = new SubType('zy');
	// alert(instance2.name); //"red,blue,green" 
	
	console.log(instance1)
	console.log(instance1.__proto__)
	console.log(instance1.__proto__.__proto__)

	console.log(SubType)
	console.log(SubType.prototype)
	console.log(SubType.prototype.__proto__)

	console.log(instance1.__proto__ == SubType.prototype)
	console.log(instance2.__proto__ == SubType.prototype)
	console.log(instance2.__proto__.__proto__ == Object.prototype)
	*/

	// 面试题一
	/*
	function Animal() {  
	    this.name = "Animal";  
	    this.showName = function() {  
	        console.log(this.name);  
	    };  
	}  
	  
	function Cat() {  
	  
	    this.name = "Cat";  
	    this._super = Cat.prototype;  
	  
	    this.showName1 = function() {  
	        console.log(this.name);  
	    };  
	  
	    this.showName2 = function() {  
	        console.log(this.name);  
	    };  
	  
	    this.showName3 = function() {  
	        console.log(this._super.name + "=>" + this.name);  
	    };  
	}  
	Cat.prototype = new Animal();  
	var cat = new Cat();  
	console.log(cat instanceof Animal);   //true  
	cat.showName1();     //"Cat"  
	cat.showName2.call(Cat.prototype);   //"Animal"  
	cat.showName3();    //"Animal" => "Cat"  

	console.log('cat',cat)
	console.log('cat',cat.__proto__)
	console.log('cat',cat.__proto__.__proto__)
	*/

	// 面试题二
	/*
	var arr = [[1,2,2],[3, 4, 5, 5],[6, 7, 8, 9,[11,12,[12,13,[14]]]],10];
	var newArr=[];
	function getAry(arrayData){
		arrayData.forEach((val)=>{
			if(typeof val == 'object'){
				arguments.callee(val)
			}else{
				newArr.push(val)
			}

		})
	}

	Array.prototype.distinct=function(){
		return this.reduce(function(newArray1,newValue){
			if (newArray1.indexOf(newValue) === -1)  
	            newArray1.push(newValue);  
	        return newArray1;
		},[])
	}

	getAry(arr)

	var  aryData = newArr.distinct(); 

	aryData.sort((a,b)=>{
		return a-b;
	})

	console.log(aryData)
	*/


	// 面试题
	/*
	function CodingMan(name){
		
		function Man(name){
			console.log(`Hi!This is ${name}`)
		}

		Man.prototype.sleep=function(time){
			setTimeout(function(){
				console.log(`Wake up after ${time}`)
			},6000)

			return this;
		}

		Man.prototype.eat=function(somethings){
			console.log(`Eat ${somethings}`)
			return this;
		}

		var man =new Man(name);

		return man;

	}
	CodingMan('Peter').eat('dinner').eat('supper')
	*/


// 闭包面试题
/*
function fun(n,o) {
  console.log('oooo',o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  
fun(0).fun(1);  
a.fun(2);  
a.fun(3);//undefined,?,?,?

var b = fun(0).fun(1).fun(2).fun(3);

var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
*/


//打印出1.2.3.4.5
/*
for (let i = 1; i <= 5; i++) {

  setTimeout( function timer() {

      console.log(i);

  }, 1000 );

}
*/

/*
// 闭包
// es6方法
var obj = {  
    name: " jsCoder",  
    skill: ["css3","html5", "es6", "react", "angular"],  
    say: function () {        
        for(let i = 0, len = this.skill.length; i< len; i++){  
            setTimeout(()=>{
                console.log("No." + i + this.name);  
                console.log(this.skill[i]);  
                console.log('--------------------------');  
            },100);  
        }  
    }  
}  

// 闭包方法
var obj = {  
    name: " jsCoder",  
    skill: ["css3","html5", "es6", "react", "angular"],  
    say: function () {        
        for(var i = 0, len = this.skill.length; i< len; i++){  

        	(
        		function(){
        			var temp = i;
        			setTimeout(function(){
		                console.log("No." + temp + obj.name);  
		                console.log(obj.skill[temp]);  
		                console.log('--------------------------');  
		            },100);
        		}
        	)()

              
        }  
    }  
}  

obj.say()
*/

	
	// function Test(){
	// 	this.funA()
	// }

	// Test.prototype.funA=function(){
	// 	console.log('hahaha')
	// }

	// var test = new Test();//调用一次

	var test=function(){
		console.log('a')
	}

	test.$={
		col:function(){
			console.log('test')
		}
	};
	test.prototype.name='xw'
	console.log(test.prototype)

	console.log(jQuery.prototype)

	console.log(jQuery === $)

	console.log({name:'1'})
	console.log(Object.prototype)

	console.log('1',Function.prototype)

	
	
	// JQ扩展方法一
	$.extend({
		sayHello:function(name){
			console.log('hello:'+name)
		}
	})
	$.sayHello('cxw')
	// JQ扩展方法二
	$.fn.myPlugin = function() {
		//在这里面,this指的是用jQuery选中的元素
		//example :$('a'),则this=$('a')
		this.css('color', 'red');
	}

	$('div').myPlugin()

	console.log($.prototype)
</script>
</html>